﻿using Microsoft.Kinect;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace DetectingKinectSencor
{
    /// <summary>
    /// The following class was provided by the book 
    /// Microsoft.Press.Programming.with.the.Kinect.for.Windows.Software.Development.Kit.Sep.2012
    /// </summary>
    class DepthStreamManager : Notifier
    {
        private bool DEBUGon = MainWindow.DEBUGdepthStreamManager;
        //Variable definition
        byte[] depthFrame32;

        private int user;
        private int realDepth;
        private byte intensity;
        byte arrayEntry32;
        byte arrayEntry33;
        byte arrayEntry34;
        byte arrayEntry35;
        private int stride;
        private Int32Rect dirtyRect;
        private short[] pixelData;

        //Constructor
        public WriteableBitmap Bitmap { get; private set; }


        ////////////////////////////////////////////////
        //              update Methode                //
        ////////////////////////////////////////////////
        public void update(PlayDepthStream frame)
        {
            pixelData = new short[frame.PixelDataLength];

            frame.CopyPixelDataTo(pixelData);


            if (depthFrame32 == null)
            {
                // Frame.width * frame.height * 4
                depthFrame32 = new byte[frame.Width * frame.Height << 2];

            }

            if (Bitmap == null)
            {
                Bitmap = new WriteableBitmap(frame.Width, frame.Height,
                                    96, 96, PixelFormats.Bgra32, null);
            }

            convertDepthFrame(pixelData);

            stride = (Bitmap.PixelWidth * Bitmap.Format.BitsPerPixel) >> 3;

            dirtyRect = new Int32Rect(0, 0, Bitmap.PixelWidth, Bitmap.PixelHeight);

            Bitmap.WritePixels(dirtyRect, depthFrame32, stride, 0);

            RaisePropertyChanged(() => Bitmap);


        }



        ////////////////////////////////////////////////
        //         ConvertDepthFrame method           //
        ////////////////////////////////////////////////
        private unsafe void convertDepthFrame(short[] depthFrame16)
        {
            fixed (short* depthFrame16Pointer = depthFrame16)
            {
                fixed (byte* depthFrame32Pointer = depthFrame32)
                {
                    short* tempDepthFrame16Pointer = depthFrame16Pointer;
                    byte* tempDepthFrame32Pointer = depthFrame32Pointer;

                    for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length
                            && i32 < depthFrame32.Length; i16++, i32 += 4)
                    {
                        user = *tempDepthFrame16Pointer & 0x07;

                        // Last use of tempDepthFrame32Pointer, here increment
                        realDepth = (*tempDepthFrame16Pointer++ >> 3);

                        intensity = (byte)(255 - (realDepth >> 5));

                        arrayEntry32 = 0;
                        arrayEntry33 = 0;
                        arrayEntry34 = 0;
                        arrayEntry35 = 255;

                        switch (user)
                        {
                            case 0: // no one
                                arrayEntry32 = (byte)(intensity >> 1);
                                arrayEntry33 = arrayEntry32;
                                arrayEntry34 = arrayEntry32;
                                break;
                            case 1:
                                arrayEntry32 = intensity;
                                break;
                            case 2:
                                arrayEntry33 = intensity;
                                break;
                            case 3:
                                arrayEntry34 = intensity;
                                break;
                            case 4:
                                arrayEntry32 = intensity;
                                arrayEntry33 = intensity;
                                break;
                            case 5:
                                arrayEntry32 = intensity;
                                arrayEntry34 = intensity;
                                break;
                            case 6:
                                arrayEntry33 = intensity;
                                arrayEntry34 = intensity;
                                break;
                            case 7:
                                arrayEntry32 = intensity;
                                arrayEntry33 = intensity;
                                arrayEntry34 = intensity;
                                break;
                        }

                        *tempDepthFrame32Pointer++ = arrayEntry32;
                        *tempDepthFrame32Pointer++ = arrayEntry33;
                        *tempDepthFrame32Pointer++ = arrayEntry34;
                        *tempDepthFrame32Pointer++ = arrayEntry35;
                        
                    }
                }
            }
        }
    }
}
